﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace FairyGUI
{
	/// <summary>
	/// Helper for drag and drop.
	/// 这是一个提供特殊拖放功能的功能类。与GObject.draggable不同，拖动开始后，他使用一个替代的图标作为拖动对象。
	/// 当玩家释放鼠标/手指，目标组件会发出一个onDrop事件。
	/// </summary>
	public class DragDropManager
	{
		private GLoader _agent;
		private object _sourceData;

		private static DragDropManager _inst;
		public static DragDropManager inst
		{
			get
			{
				if (_inst == null)
					_inst = new DragDropManager();
				return _inst;
			}
		}

		public DragDropManager()
		{
			_agent = (GLoader)UIObjectFactory.NewObject(ObjectType.Loader);
			_agent.gameObjectName = "DragDropAgent";
			_agent.SetHome(GRoot.inst);
			_agent.touchable = false;//important
			_agent.draggable = true;
			_agent.SetSize(100, 100);
			_agent.SetPivot(0.5f, 0.5f, true);
			_agent.align = AlignType.Center;
			_agent.verticalAlign = VertAlignType.Middle;
			_agent.sortingOrder = int.MaxValue;
			_agent.onDragEnd.Add(__dragEnd);
		}

		/// <summary>
		/// Loader object for real dragging.
		/// 用于实际拖动的Loader对象。你可以根据实际情况设置loader的大小，对齐等。
		/// </summary>
		public GLoader dragAgent
		{
			get { return _agent; }
		}

		/// <summary>
		/// Is dragging?
		/// 返回当前是否正在拖动。
		/// </summary>
		public bool dragging
		{
			get { return _agent.parent != null; }
		}

		/// <summary>
		/// Start dragging.
		/// 开始拖动。
		/// </summary>
		/// <param name="source">Source object. This is the object which initiated the dragging.</param>
		/// <param name="icon">Icon to be used as the dragging sign.</param>
		/// <param name="sourceData">Custom data. You can get it in the onDrop event data.</param>
		/// <param name="touchPointID">Copy the touchId from InputEvent to here, if has one.</param>
		public void StartDrag(GObject source, string icon, object sourceData, int touchPointID = -1)
		{
			if (_agent.parent != null)
				return;

			_sourceData = sourceData;
			_agent.url = icon;
			GRoot.inst.AddChild(_agent);
			_agent.xy = GRoot.inst.GlobalToLocal(Stage.inst.GetTouchPosition(touchPointID));
			_agent.StartDrag(touchPointID);
		}

		/// <summary>
		/// Cancel dragging.
		/// 取消拖动。
		/// </summary>
		public void Cancel()
		{
			if (_agent.parent != null)
			{
				_agent.StopDrag();
				GRoot.inst.RemoveChild(_agent);
				_sourceData = null;
			}
		}

		private void __dragEnd(EventContext evt)
		{
			if (_agent.parent == null) //cancelled
				return;

			GRoot.inst.RemoveChild(_agent);

			object sourceData = _sourceData;
			_sourceData = null;

			GObject obj = GRoot.inst.touchTarget;
			while (obj != null)
			{
				if (obj is GComponent)
				{
					if (!((GComponent)obj).onDrop.isEmpty)
					{
						obj.RequestFocus();
						((GComponent)obj).onDrop.Call(sourceData);
						return;
					}
				}

				obj = obj.parent;
			}
		}
	}
}